#ifndef _WX_DND_H_BASE_
#define _WX_DND_H_BASE_

#include "wx/defs.h"

#if wxUSE_DRAG_AND_DROP

#include "wx/dataobj.h"
#include "wx/cursor.h"

enum {
  wxDrag_CopyOnly    = 0, // allow only copying
  wxDrag_AllowMove   = 1, // allow moving (copying is always allowed)
  wxDrag_DefaultMove = 3  // the default operation is move, not copy
};

// result of wxDropSource::DoDragDrop() call
enum wxDragResult {
  wxDragError,    // error prevented the d&d operation from completing
  wxDragNone,     // drag target didn't accept the data
  wxDragCopy,     // the data was successfully copied
  wxDragMove,     // the data was successfully moved (MSW only)
  wxDragLink,     // operation is a drag-link
  wxDragCancel    // the operation was cancelled by user (not an error)
};

bool wxIsDragResultOk( wxDragResult res );

class wxDropSourceBase {
  public:
    wxDropSourceBase( const wxCursor &cursorCopy = wxNullCursor,
                      const wxCursor &cursorMove = wxNullCursor,
                      const wxCursor &cursorStop = wxNullCursor )
      : m_cursorCopy( cursorCopy ),
        m_cursorMove( cursorMove ),
        m_cursorStop( cursorStop ) { m_data = ( wxDataObject * )NULL; }
    virtual ~wxDropSourceBase() { }

    // set the data which is transfered by drag and drop
    void SetData( wxDataObject& data ) { m_data = &data; }

    wxDataObject *GetDataObject() { return m_data; }

    // set the icon corresponding to given drag result
    void SetCursor( wxDragResult res, const wxCursor& cursor ) {
      if( res == wxDragCopy ) {
        m_cursorCopy = cursor;
      } else if( res == wxDragMove ) {
        m_cursorMove = cursor;
      } else
      { m_cursorStop = cursor; }
    }

    virtual wxDragResult DoDragDrop( int flags = wxDrag_CopyOnly ) = 0;
    virtual bool GiveFeedback( wxDragResult ( effect ) ) { return false; }

  protected:
    const wxCursor& GetCursor( wxDragResult res ) const {
      if( res == wxDragCopy ) {
        return m_cursorCopy;
      } else if( res == wxDragMove ) {
        return m_cursorMove;
      } else
      { return m_cursorStop; }
    }

    // the data we're dragging
    wxDataObject *m_data;

    // the cursors to use for feedback
    wxCursor m_cursorCopy,
             m_cursorMove,
             m_cursorStop;

    DECLARE_NO_COPY_CLASS( wxDropSourceBase )
};

// ----------------------------------------------------------------------------
// wxDropTarget should be associated with a window if it wants to be able to
// receive data via drag and drop.
//
// To use this class, you should derive from wxDropTarget and implement
// OnData() pure virtual method. You may also wish to override OnDrop() if you
// want to accept the data only inside some region of the window (this may
// avoid having to copy the data to this application which happens only when
// OnData() is called)
// ----------------------------------------------------------------------------

class wxDropTargetBase {
  public:
    // ctor takes a pointer to heap-allocated wxDataObject which will be owned
    // by wxDropTarget and deleted by it automatically. If you don't give it
    // here, you can use SetDataObject() later.
    wxDropTargetBase( wxDataObject *dataObject = ( wxDataObject* )NULL ) { m_dataObject = dataObject; m_defaultAction = wxDragNone; }
    // dtor deletes our data object
    virtual ~wxDropTargetBase() { delete m_dataObject; }

    // get/set the associated wxDataObject
    wxDataObject *GetDataObject() const
    { return m_dataObject; }
    void SetDataObject( wxDataObject *dataObject ) {
      if( m_dataObject ) {
        delete m_dataObject;
      }
      m_dataObject = dataObject;
    }
    virtual wxDragResult OnEnter( wxCoord x, wxCoord y, wxDragResult def ) { return OnDragOver( x, y, def ); }
    virtual wxDragResult OnDragOver( wxCoord ( x ), wxCoord ( y ),wxDragResult def ) { return def; }
    virtual void OnLeave() { }
    virtual bool OnDrop( wxCoord x, wxCoord y ) = 0;
    virtual wxDragResult OnData( wxCoord x, wxCoord y, wxDragResult def ) = 0;
    virtual bool GetData() = 0;
    void SetDefaultAction( wxDragResult action ) { m_defaultAction = action; }
    wxDragResult GetDefaultAction() { return m_defaultAction; }
  protected:
    wxDataObject *m_dataObject;
    wxDragResult m_defaultAction;

    DECLARE_NO_COPY_CLASS( wxDropTargetBase )
};

#include "wx/gtk/dnd.h"

class wxTextDropTarget : public wxDropTarget {
  public:
    wxTextDropTarget();

    virtual bool OnDropText( wxCoord x, wxCoord y, const wxString& text ) = 0;

    virtual wxDragResult OnData( wxCoord x, wxCoord y, wxDragResult def );

  private:
    DECLARE_NO_COPY_CLASS( wxTextDropTarget )
};

class wxFileDropTarget : public wxDropTarget {
  public:
    wxFileDropTarget();
    virtual bool OnDropFiles( wxCoord x, wxCoord y,
                              const wxArrayString& filenames ) = 0;

    virtual wxDragResult OnData( wxCoord x, wxCoord y, wxDragResult def );

  private:
    DECLARE_NO_COPY_CLASS( wxFileDropTarget )
};

#endif // wxUSE_DRAG_AND_DROP

#endif // _WX_DND_H_BASE_
